<template>
	<view class="category">
		<!-- 搜索框 -->
		<view class="search">
			<view class="searchInput" @click="go">
				<u-icon name="search" color="#909199" :size="26"></u-icon>
				<text class="inputTxt">请输入搜索关键词</text>
			</view>
		</view>
		<!-- 加载效果 -->
		<block v-if='status == "loading"'>
			<u-loadmore :status="status"></u-loadmore>
		</block>
		<!-- 滚动区域 -->
		<view v-else-if='status == "nomore"' class="menuwrap">
			<!-- 左侧滚动区域：纵向滚动，开启滑动的动画效果，动态设置纵向滚动条在每次点击后的位置 -->
			<scroll-view scroll-y scroll-with-animation class="leftNav" :scroll-top="scrollTop">
				<view v-for="(item,index) in list" :key="item.name" class="tabItem" @tap.stop="toggleMenu(index)">
					<text :class="currentIndex == index ? 'line active' : 'line'">{{item.name}}</text>
					<!-- <text :class="['line', currentIndex == index ? 'active']">{{item.name}}</text> -->
				</view>
			</scroll-view>
			<!-- 右侧滚动区域 -->
			<scroll-view scroll-y scroll-with-animation class="rightNav" :scroll-top="scrollRightTop"
				@scroll="rightScroll">
				<view class="pageView">
					<view class="section" v-for="(item,index) in list" :key="item.name" :id="'item'+index">
						<view class="title">
							<text>{{item.name}}</text>
							<view class="aside">
								<!-- key值不可重复 -->
								<view class="li" v-for="(val,i) in item.foods" :key="i">
									<image class="li-img" :src="val.icon"></image>
									<view class="li-name">{{val.name}}</view>
								</view>
							</view>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	import {
		apiClassfy
	} from "../../api/mock"
	export default {
		data() {
			return {
				list: [], //分类数据
				status: 'loading',
				currentIndex: 0,
				scrollTop: 0, //每次点击的滚动条位置变量，默认从第一个开始
				oldScrollTop: 0, //上一次点击的滚动条位置
				menuHeight: 0, //整个左侧菜单的高度
				menuItemHeight: 0, //左侧单个菜单的高度
				TopArr: [], //根据标签顺序，获取每个section的高度
				scrollRightTop: 0, //右侧菜单的滚动位置变量
				timer: '', //
			}
		},
		onLoad() {
			this.getClassfy()
		},
		onReady() {
			//当页面初次渲染完成后，获取所有section的高度（右侧菜单的所有高度）
			this.getMenuItemTopDistance()
		},
		methods: {
			go() {
				uni.navigateTo({
					url: '/pages/find/find'
				})
			},
			/* 发起请求的函数 */
			getClassfy() {
				apiClassfy().then((res) => {
					this.status = 'nomore'
					this.list = [...res]
				}).catch((err) => {

				})
			},
			/* 工具函数：获取右侧每个子菜单的高度（到顶部的距离） */
			getMenuItemTopDistance() {
				new Promise((resolve) => {
					let query = uni.createSelectorQuery();
					//从所有section中获取每个节点的布局位置信息
					query.selectAll('.section').boundingClientRect((data) => {
						if (!data.length) {
							setTimeout(() => {
								this.getMenuItemTopDistance()
							}, 20)
							return;
						}
						//遍历：获取每个section的top坐标，计算出距离第一个置顶的菜单距离
						data.forEach((item) => {
							this.TopArr.push(item.top - data[0].top);
							resolve();
						})
					}).exec();
				})
			},
			/* 工具函数:获取指定标签的整体高度以及单个标题的高度(标签设置为参数)：为了让toggleMenu做菜单的定位居中 */
			/* elClass:你想要获取的标签选择器名称 */
			/* dataVal参数：动态给不确认的data变量赋值 */
			getElRect(elClass, dataVal) {
				new Promise((reslove, reject) => {
					//获取当前传递过来的标签节点对象
					let query = uni.createSelectorQuery().in(this);
					//获取指定标签选择器中的尺寸宽高
					query.select("." + elClass).fields({
						size: true
					}, (res) => {
						//如果页面渲染加载较慢，有可能标签在此时仍未获取成功
						if (!res) {
							setTimeout(() => {
								//过一段时间再次执行本函数即可
								this.getElRect(elClass)
							}, 20)
							return;
						}
						//将this作为数组，将dataVal作为下标；根据需求，从res内提取所需信息
						this[dataVal] = res.height; //this.menuItemHeight = 55
					}).exec();
				})
			},

			/* 切换左侧菜单，促使被点击的菜单剧中显示（排除最开始和最后鱼的菜单） */
			async toggleMenu(index) {
				//判断：当前点击的菜单下标跟当前循环的菜单循环下标是否一致；赋值
				//重复点击
				if (index == this.currentIndex) return
				//将上一次获取到的滚动条位置赋值给右侧滚动变量
				this.scrollRightTop = this.oldScrollTop
				//this.$nextTick().将Dom更新更改实际，下一次数据更新之后，Dom更新之前
				this.$nextTick(function() {
					//将本次点击的下标index，从section高度数组中获取对应的元素值并赋值给右侧滚动高度
					this.scrollRightTop = this.TopArr[index]
					//将本次点击的下标，赋值给下一次选中下标变量
					this.currentIndex = index
					//调用滚动动画计算过程
					this.leftMenuStatus(index)
				})
				//将当前被点击的菜单相关选择器传递过去
				// this.getElRect('tabItem','menuItemHeight')
			},
			//设置左侧菜单的滚动动画状态：居中菜单
			async leftMenuStatus(index) {
				//将本次点击的下标，赋值给当前选择器样式判断变量
				this.currentIndex = index;
				//如果两个菜单的高度都为0的情况下，表示菜单的高度并未获取
				if (this.menuHeight == 0 || this.menuItemHeight == 0) {
					//获取整个菜单的高度
					await this.getElRect('leftNav', 'menuHeight')
					//获取单个菜单的高度
					await this.getElRect('tabItem', 'menuItemHeight')
				}
				//计算出当前所点击的菜单，需要将滚动条设置到哪个位置上
				this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2
			},
			/* 右侧菜单 */
			async rightScroll(e) {
				//将本次的滚动顶点坐标赋值给oldScrollTop
				this.oldScrollTop = e.detail.scrollTop;
				//保险机制：当前事件调用工具函数之前，先判断工具函数的返回值/data数据是否已经有结果，如果没有结果，那就需要再次执行工具函数
				if (this.TopArr.length == 0) {
					await this.getMenuItemTopDistance();
				}
				if (!this.menuHeight) {
					await this.getElRect('leftNav', 'menuHeight')
				}
				//定时器：节流
				this.timer = setTimeout(() => {
					//延迟定时器启动后，内部清空
					this.timer = null;
					//计算出右侧菜单垂直中点的位置
					let scrollHeight = this.menuHeight / 2 + e.detail.scrollTop;
					//遍历所有section菜单的高度
					for (let i = 0; i < this.TopArr.length; i++) {
						let heigth1 = this.TopArr[i]; //当前i的高度：女装section
						let heigth2 = this.TopArr[i + 1]; //下一个i的高度：美食section
						//还没有到最后一个section 或者 滚动的中间点大于当前section的高度（滚动已经离开了当前菜单） 同时 滚动的中间点小于下一个菜单（下一个菜单还没有滚动完）
						if (!heigth2 || scrollHeight >= heigth1 && scrollHeight < heigth2) {
							this.leftMenuStatus(i);
							return
						}
					}
				}, 100)
			}
		}
	}
</script>

<style lang="scss" scoped>
	/* calc():计算复杂的公式，计算根据设备屏幕尺寸计算出目标区域的自适应高度/宽度 */
	.category {
		height: calc(100vh);
		display: flex;
		//纵向排列
		flex-direction: column;
		/* #ifdef H5*/
		height: calc(100vh - var(--window-top));

		/* #endif*/
		/* 搜索框样式 */
		.search {
			padding: 8px 20px;

			.searchInput {
				background-color: rgb(234, 234, 234);
				border-radius: 20px;
				display: flex;
				align-items: center;
				padding: 0 8px;

				.inputTxt {
					font-size: 14px;
					color: $u-tips-color;
					margin-left: 10px;
				}
			}
		}

		.menuwrap {
			background-color: white;
			display: flex;
			flex: 1; //表示：在100vh的基础下，减去搜索框所占的高度，剩余高度由该标签继承
			overflow: hidden; //

			//左侧
			.leftNav {
				width: 25%;
				//高度100%的前提是：父级标签有明确高度，100%与父级标签的高度一致【父级标签没有高度时设置高度百分百相当于没有高度】
				height: 100%;
				background-color: orange;

				.tabItem {
					height: 55px;
					background-color: #f6f6f6;
					box-sizing: bord;
					font-size: 13px;
					color: #444;
					font-weight: 400;

					.line {
						width: 100%;
						height: 100%;
						display: flex;
						align-items: center;
						justify-content: center;

						/* &表示当前所在区域的class选择器的.tabItem */
						&.active {
							color: #000;
							font-size: 15px;
							font-weight: 600;
							background-color: white;
							position: relative;

							//::before伪类:在指定标签之前添加的效果(不用标签包裹的)
							//::after伪类:在指定标签之后添加的效果
							&::before {
								content: "";
								position: absolute;
								height: 16px;
								left: 0;
								top: 19px;
								border: 2px solid #3c9cff;
							}
						}
					}
				}
			}

			//右侧
			.rightNav {
				.pageView {
					padding: 8px;

					.section {
						margin-bottom: 15px;
						padding: 8px;
						border-radius: 4px;

						&:last-child {
							min-height: 100vh;
						}

						.title {
							font-size: 14px;
							color: #303133;
							font-weight: bold;
						}

						.aside {
							display: flex;
							flex-wrap: wrap;

							.li {
								width: 33.33%;
								display: flex;
								align-items: center;
								justify-content: center;
								flex-direction: column;
								margin-top: 10px;

								.li-img {
									width: 60px;
									height: 60px;
								}

								.li-name {
									font-weight: normal;
									font-size: 12px;
									color: #303133;
								}
							}
						}
					}
				}
			}
		}
	}
</style>